home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * ppm.c
- *
- * This module contains the code to read and write the PPM file format.
- *
- * from Persistence of Vision(tm) Ray Tracer
- * Copyright 1996 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file. If
- * POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- * Forum. The latest version of POV-Ray may be found there as well.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- * Original patch copyright 1994 Tim Rowley
- * Updated for POV 3.0 by Chris Cason, Jan '95.
- *
- *****************************************************************************/
-
- /****************************************************************************
- * The format is as follows:
- *
- * (header:)
- * P3 - ASCII data OR
- * P6 - raw binary data
- * # hello - optional comment(s)
- * wwww hhhh - Width, Height (ASCII text)
- * # world - optional comment(s)
- * nnn - maximum color (nnn = bright, 0 = black)
- *
- * (each pixel: one of the following)
- * rr gg bb - Red, green, blue of intensity 0-nnn (binary byte)
- * RRR GGG BBB - Red, green, blue of intensity 0-nnn (ASCII number)
- *
- *****************************************************************************/
-
- #include "frame.h"
- #include "povproto.h"
- #include "povray.h"
- #include "optout.h"
- #include "pgm.h"
- #include "ppm.h"
-
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
-
- /*****************************************************************************
- * Local typedefs
- ******************************************************************************/
-
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
-
- static int PPM_Line_Number;
-
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
-
- static int Open_PPM_File PARAMS ((FILE_HANDLE *handle, char *name, int *width,
- int *height, int buffer_size, int mode));
- static void Write_PPM_Line PARAMS ((FILE_HANDLE *handle, COLOUR *line_data,
- int line_number));
- static int Read_PPM_Line PARAMS((FILE_HANDLE *handle, COLOUR *line_data,
- int *line_number));
- static void Close_PPM_File PARAMS((FILE_HANDLE *handle));
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
-
- FILE_HANDLE *Get_PPM_File_Handle()
- {
- FILE_HANDLE *handle;
-
- handle = (FILE_HANDLE *) POV_MALLOC(sizeof(FILE_HANDLE), "PPM file handle") ;
-
- handle->Open_File_p = Open_PPM_File;
- handle->Write_Line_p = Write_PPM_Line;
- handle->Read_Line_p = Read_PPM_Line;
- handle->Read_Image_p = Read_PPM_Image;
- handle->Close_File_p = Close_PPM_File;
-
- handle->file = NULL;
- handle->buffer = NULL;
- handle->buffer_size = 0;
-
- return (handle);
- }
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
-
- static int Open_PPM_File(handle, name, width, height, buffer_size, mode)
- FILE_HANDLE *handle;
- char *name;
- int *width;
- int *height;
- int buffer_size;
- int mode;
- {
- char type;
- int input;
- char junk[512];
-
- handle->mode = mode;
- handle->filename = name;
- PPM_Line_Number = 0;
-
- switch (mode)
- {
- case READ_MODE:
-
- /* We can't resume from stdout. */
- if (opts.Options & TO_STDOUT ||
- (handle->file = fopen(name, READ_FILE_STRING)) == NULL)
- {
- Status_Info("\n");
- return(0);
- }
-
- if (buffer_size != 0)
- {
- handle->buffer = POV_MALLOC((size_t)buffer_size, "PPM file buffer") ;
- setvbuf(handle->file, handle->buffer, _IOFBF, buffer_size);
- }
-
- if (fscanf(handle->file, "P%c\n", &type) != 1 || type != '6')
- {
- return(0);
- }
-
- /* Ignore any comments (if they are written) */
-
- while ((input = fgetc(handle->file)) == '#')
- {
- fgets(junk, 512, handle->file);
- }
-
- ungetc(input, handle->file);
-
- if (fscanf(handle->file, "%d %d\n255\n", width, height) != 2)
- {
- return(0);
- }
-
- Status_Info("\nResuming interrupted trace from %s",handle->filename);
-
- handle->width = *width;
- handle->height = *height;
- handle->buffer_size = buffer_size;
-
- break;
-
- case WRITE_MODE:
-
- if (opts.Options & TO_STDOUT)
- {
- buffer_size = 0;
- handle->file = stdout;
- }
- else
- {
- if ((handle->file = fopen(name, WRITE_FILE_STRING)) == NULL)
- {
- return(0);
- }
- }
-
- if (buffer_size != 0)
- {
- handle->buffer = POV_MALLOC((size_t)buffer_size, "PPM file buffer") ;
- setvbuf(handle->file, handle->buffer, _IOFBF, buffer_size);
- }
-
- fprintf(handle->file, "P6\n");
-
- #ifdef POV_COMMENTS
- #ifdef TRACER
- fprintf(handle->file, "# Author: %s\n", TRACER);
- #endif
-
- fprintf(handle->file, "# Source: Persistence of Vision(tm) Ray Tracer v%s%s\n",
- POV_RAY_VERSION, COMPILER_VER);
-
- if (!(opts.Options & TO_STDOUT))
- {
- fprintf(handle->file, "# Input File: %s\n", opts.Input_File_Name);
- }
-
- if (opts.FrameSeq.Clock_Value != 0)
- {
- fprintf(handle->file, "# POV Clock: %g\n", opts.FrameSeq.Clock_Value);
- }
-
- if (opts.Quality != 9)
- {
- fprintf(handle->file, "# Rendering Quality: %d\n", opts.Quality);
- }
- #endif /* POV_COMMENTS */
-
- fprintf(handle->file, "%d %d\n255\n", *width, *height);
-
- handle->width = *width;
- handle->height = *height;
-
- handle->buffer_size = buffer_size;
-
- break;
-
- case APPEND_MODE:
-
- if (opts.Options & TO_STDOUT)
- {
- buffer_size = 0;
- handle->file = stdout;
- }
- else
- {
- if ((handle->file = fopen(name, APPEND_FILE_STRING)) == NULL)
- {
- return(0);
- }
- }
-
- if (buffer_size != 0)
- {
- handle->buffer = POV_MALLOC((size_t)buffer_size, "PPM file buffer") ;
- setvbuf(handle->file, handle->buffer, _IOFBF, buffer_size);
- }
-
- handle->buffer_size = buffer_size;
-
- break;
- }
-
- return(1);
- }
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
-
- static void Write_PPM_Line(handle, line_data, line_number)
- FILE_HANDLE *handle;
- COLOUR *line_data;
- int line_number;
- {
- unsigned int gray;
- register int x;
-
- for (x = 0 ; x < handle->width ; x++)
- {
- if (opts.Options & HF_GRAY_16) /* 16 bit grayscale output */
- {
- gray = ((0.30 * line_data[x][RED]) +
- (0.59 * line_data[x][GREEN]) +
- (0.11 * line_data[x][BLUE])) * 65535;
-
- if ((putc((gray >> 8) & 0xFF, handle->file) == EOF) ||
- (putc(gray & 0xFF, handle->file) == EOF) ||
- (putc(0, handle->file) == EOF))
- {
- Error("Error writing PPM output data to %s.\n",handle->filename);
- }
- }
- else /* Normal 24 bit pixel coloring */
- {
- if ((putc((int)floor(line_data[x][RED] * 255.0), handle->file) == EOF) ||
- (putc((int)floor(line_data[x][GREEN]*255.0), handle->file) == EOF) ||
- (putc((int)floor(line_data[x][BLUE]*255.0), handle->file) == EOF))
- {
- Error("Error writing PPM output data to %s.\n",handle->filename);
- }
- }
- }
-
- PPM_Line_Number++;
-
- if (handle->buffer_size == 0)
- {
- /* close and reopen file for integrity in case we crash */
-
- fflush(handle->file);
-
- if (!(opts.Options & TO_STDOUT))
- {
- handle->file = freopen(handle->filename,APPEND_FILE_STRING,handle->file);
- }
- }
- }
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
-
- static int Read_PPM_Line(handle, line_data, line_number)
- FILE_HANDLE *handle;
- COLOUR *line_data;
- int *line_number;
- {
- int data, i;
-
- if ((data = getc(handle->file)) == EOF)
- {
- return (0);
- }
-
- ungetc(data, handle->file);
-
- *line_number = PPM_Line_Number++;
-
- for (i = 0 ; i < handle->width ; i++)
- {
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- line_data[i][RED] = (DBL) data / 255.0;
-
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- line_data[i][GREEN] = (DBL) data / 255.0;
-
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- line_data[i][BLUE] = (DBL) data / 255.0;
- }
-
- return (1);
- }
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
-
- static void Close_PPM_File(handle)
- FILE_HANDLE *handle;
- {
- if (handle->file)
- {
- fflush(handle->file);
-
- /* Close and reopen file (if not stdout) for integrity in case we crash */
-
- if (!(opts.Options & TO_STDOUT))
- fclose(handle->file);
- }
-
- if (handle->buffer != NULL)
- {
- POV_FREE(handle->buffer);
- }
-
- handle->file = NULL;
- handle->buffer = NULL;
- }
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * DESCRIPTION
- *
- * CHANGES
- *
- ******************************************************************************/
-
- void Read_PPM_Image(Image, name)
- IMAGE *Image;
- char *name;
- {
- char type;
- int width, height;
- int depth;
- char input;
- char junk[512];
- int x, y;
- int data;
- IMAGE_LINE *line_data;
- FILE *infile;
-
- if ((infile = Locate_File(name, READ_FILE_STRING, ".ppm", ".PPM",TRUE)) == NULL)
- {
- Error("Error opening PPM image %s.\n", name);
- }
-
- if (fscanf(infile, "P%c\n", &type) != 1 || (type != '3' && type != '6'))
- {
- Error ("File is not in PPM format.\n", name);
- }
-
- /* Ignore any comments */
-
- while ((input = fgetc(infile)) == '#')
- {
- fgets(junk, 512, infile);
- }
-
- ungetc(input, infile);
-
- if (fscanf(infile, "%d %d\n", &width, &height) != 2)
- {
- Error ("Error reading width or height from PPM image.\n", name);
- }
-
- /* Ignore any comments */
- while ((input = fgetc(infile)) == '#')
- {
- fgets(junk, 512, infile);
- }
-
- ungetc(input, infile);
-
- if (fscanf(infile, "%d\n", &depth) != 1 || depth > 255 || depth < 1)
- {
- Error ("Unsupported number of colors (%d) in PPM image.\n", depth);
- }
-
- Image->width = (DBL)(Image->iwidth = width);
- Image->height = (DBL)(Image->iheight = height);
-
- Image->Colour_Map_Size = 0;
-
- Image->Colour_Map = NULL;
-
- Image->data.rgb_lines = (IMAGE_LINE *) POV_MALLOC(Image->iheight * sizeof (IMAGE_LINE), "PPM image");
-
- for (y = 0; y < height; y++)
- {
- line_data = &Image->data.rgb_lines[y];
-
- line_data->red = (unsigned char *)POV_MALLOC(width,"PPM image line");
- line_data->green = (unsigned char *)POV_MALLOC(width,"PPM image line");
- line_data->blue = (unsigned char *)POV_MALLOC(width,"PPM image line");
- line_data->transm = (unsigned char *)NULL;
-
- if (type == '3') /* ASCII data to be input */
- {
- for (x = 0; x < width; x++)
- {
- if (fscanf(infile,"%d",&data) != 1)
- {
- Error("Error reading data from PPM image.\n");
- }
-
- line_data->red[x] = data*255/depth;
-
- if (fscanf(infile,"%d",&data) != 1)
- {
- Error("Error reading data from PPM image.\n");
- }
-
- line_data->green[x] = data*255/depth;
-
- if (fscanf(infile,"%d",&data) != 1)
- {
- Error("Error reading data from PPM image.\n");
- }
-
- line_data->blue[x] = data*255/depth;
- }
- }
- else /* (type == '6') Raw binary data to be input */
- {
- for (x = 0; x < width; x++)
- {
- if ((data = getc(infile)) == EOF)
- {
- Error("Error reading data from PPM image.\n");
- }
-
- line_data->red[x] = data*255/depth;
-
- if ((data = getc(infile)) == EOF)
- {
- Error("Error reading data from PPM image.\n");
- }
-
- line_data->green[x] = data*255/depth;
-
- if ((data = getc(infile)) == EOF)
- {
- Error("Error reading data from PPM image.\n");
- }
-
- line_data->blue[x] = data*255/depth;
- }
- }
- }
-
- fclose(infile);
- }
-